package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"net/http"
	"time"
)

// 定义中间件
func time1(c *gin.Context) {  // 计算请求耗时

	fmt.Println("m1 time start.....")
	start := time.Now()

	c.Next()   // 这个函数可以让出执行权， 执行后序的所有处理函数， 执行完毕后，执行权返回当前位置（也就是处理函数全部执行完， 再统计时间）
	//c.Abort()  这个函数是 阻止后序的函数调用，直接执行完当前函数后（如果有上级函数没执行完，就返回上级函数继续执行），执行后就结束了。
	cost := time.Since(start)
	fmt.Printf("handler spend time is %v\n", cost)
}

type UserInfo struct {
	Id			int        `gorm:"not null pk autoincrement"`
	Name        string
	SysCreated  int
	SysUpdated  int
}

func main() {
	// 后面的参数，解析时间，本地时间
	dsn := "root:123456@tcp(127.0.0.1:3306)/superstar?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {panic(err)}

	// 1. 插入数据
	//u1 := UserInfo{Name: "黄栋林", SysCreated: 30, SysUpdated: 20}
	//db.Create(&u1)

	// 2. 获取数据
	var u UserInfo
	db.First(&u)
	fmt.Printf("u: %#v\n", u)

	// 更新数据
	//u.Id = 5
	//db.Model(&u).Update("name", "hello")

	// 删除 id 大于 6 的数据
	db.Where("Id > ?", 6).Delete(UserInfo{})

	// gorm.Model 嵌入到 自定义的结构体中， 默认添加四个字段， 查看源码可知。

	r := gin.Default()
	r.LoadHTMLFiles("./irisDome/hello.html")  // 指定单个， 或者并列枚举多个。 下面 直接 HTML("hello.html") 即可
	// 静态文件处理， 这里和 django 是一样的。
	r.Static("/static", "./static")  // 第一个参数标识 以 static 开头的即为静态文件， 去 ./static 目录下去寻找对应的静态文件
	r.GET("/ping", func(c *gin.Context){
		c.JSON(200, gin.H{
			"message": "pong",
		})
	}, time1)  // 使用中间件

	r.GET("/index", func(c *gin.Context){
		c.HTML(http.StatusOK, "hello.html", gin.H{
			"Title": "gin模板",
			"Content": "第一次加载gin模板",
		})
	})

	r.GET("/xxx/:name/*age", func(context *gin.Context) {
		// /xxx/:name/*age   ,  *age 可以匹配一切路径， 只要开头是  /xxx/:name/ 即可， 比如http://127.0.0.1:8080/xxx/xiaoming/19/13/14 得到的是：{"age":"/19/13/14","name":"xiaoming"}
		name := context.Param("name")
		age := context.Param("age")
		context.JSON(http.StatusOK, gin.H{
			"name": name,
			"age": age,
		})

		// 数据绑定:  配合结构体的 tag， 这里有很多绑定的方法， ShouldBind 是绑定json， get, form表单都绑定
		//context.ShouldBind()
		//context.Bind()
		//context.Should
		//context.SaveUploadedFile()
		//context.Redirect()
		// context.Any()  处理创建的 Post， Get， Delete等等请求， 内部通过switch 匹配
		context.Next()
	})

	// 路由组的定义
	xxx := r.Group("/xxx")
	xxx.Use(time1)  // 使用中间件
	{
		xxx.POST("/ccc", func(context *gin.Context){})
		// 还支持嵌套，内部还可加 路由组
		sub := r.Group("/sub")
		{
			sub.GET("/q", func(context *gin.Context) {})
		}
	}


	r.Run()
}



